﻿using System.Linq.Expressions;

using Tszy.Unlimited.Base.Collections;
using Tszy.Unlimited.Base.Exceptions;

namespace Tszy.Unlimited.Data.AdoNet.Sql.Components.Expressions.Filters
{
    /// <summary>
    /// 实现 linq 中的 OrderBy 函数。
    /// </summary>
    internal class OrderByExpressionExecutor : ExpressionExecutorBase
    {
        private readonly MonoConcurrentDictionary<string, string> _sql = new MonoConcurrentDictionary<string, string>();

        /// <summary>
        /// 初始化。
        /// </summary>
        public OrderByExpressionExecutor() : base(ExpressionKey.ORDERBY)
        {
        }

        /// <summary>
        ///
        /// </summary>
        /// <param name="context"></param>
        /// <param name="expression"></param>
        /// <returns></returns>
        public override ExpressionExecutorResult Execute(ExpressionContext context, Expression expression)
        {
            if (expression == null)
                throw new MainApplicationException("OrderBy 函数处理失败，表达式不可以是 null。");

            if (!string.IsNullOrWhiteSpace(context.Identity))
            {
                var key = context.Identity + "_orderby_" + expression.ToString().Replace(" ", "_");

                if (!_sql.ContainsKey(key))
                {
                    var sql = ExecuteHandler(context, expression);

                    _sql[key] = sql;
                }

                var orderBy = _sql[key] ?? string.Empty;

                //orderBy += " ASC";

                context.OrderBy.Enqueue(new ExpressionOrderByParameter { Name = orderBy, Sort = "ASC" });
                //context.OrderBy[orderBy] = "ASC";

                //if (string.IsNullOrWhiteSpace(context.OrderBy))
                //{
                //    context.OrderBy = orderBy;
                //}
                //else
                //{
                //    context.OrderBy += ", " + orderBy;
                //}
            }
            else
            {
                var orderBy = ExecuteHandler(context, expression);

                //orderBy += " ASC";

                context.OrderBy.Enqueue(new ExpressionOrderByParameter { Name = orderBy, Sort = "ASC" });
                //context.OrderBy[orderBy] = "ASC";

                //if (string.IsNullOrWhiteSpace(context.OrderBy))
                //{
                //    context.OrderBy = orderBy;
                //}
                //else
                //{
                //    context.OrderBy += ", " + orderBy;
                //}
            }

            return ResultSuccess();
        }

        private string ExecuteHandler(ExpressionContext context, Expression expression)
        {
            return GetParameterNameByLambda(context, expression);
        }
    }
}